﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DllLmportIF.HKCharmer
{
    /// <summary>
    /// 相机帮助类
    /// </summary>
    public class CharmerHelp
    {


        /// <summary>
        /// IP地址
        /// </summary>
        public string IpAdress;

        /// <summary>
        /// 端口号
        /// </summary>
        public Int32 Port;

        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName;

        /// <summary>
        /// 密码
        /// </summary>
        public string PassWord;

        /// <summary>
        /// 抓图通道
        /// </summary>
        public int CatchImageChannel = 1;

        /// <summary>
        /// 是否完成初始化
        /// </summary>
        private static bool m_bInitSDK = false;

        /// <summary>
        /// 用户名
        /// </summary>
        private int m_UserID = -1;

        /// <summary>
        /// 预览视频的函数句柄
        /// </summary>
        private Int32 m_lRealHandle = -1;

        /// <summary>
        /// 预览视频的回调接口
        /// </summary>
        public CHCNetSDK.REALDATACALLBACK RealData = null;

        /// <summary>
        /// 相机回调函数
        /// </summary>
        public Action<Byte[], string> ResultByteCallBaack = null;

        private readonly object m_LockObject = new object();

        /// <summary>
        /// 是否继续抓图
        /// </summary>
        private volatile bool m_IsContinueCatch = true;

        /// <summary>
        /// 是否开始抓图
        /// </summary>
        private volatile bool m_HaveStartCatchThread = false;

        /// <summary>
        /// 是否开始抓图的锁
        /// </summary>
        private  readonly object m_LockHaveStartCatchThread=new object();

        public CharmerHelp()
        {
            //List<string> lisPath = new List<string>();
            //string path = AppDomain.CurrentDomain.BaseDirectory + @"HKCharmerDLL";
            //lisPath.Add(path);
            //DllImportHelp.AddEnvironmentPaths(lisPath);
        }

        //public CharmerHelp(HKCharmerConfig hkCharmerConfig)
        //{
        //    this.IpAdress = hkCharmerConfig.IP;//IP地址
        //    this.Port = hkCharmerConfig.Port;//端口号
        //    this.UserName = hkCharmerConfig.UserName;//用户名
        //    this.PassWord = hkCharmerConfig.PassWord;//密码
        //    this.CatchImageChannel = hkCharmerConfig.CatchImageChannel;//抓图通道
        //}

        /// <summary>
        /// 添加路径
        /// </summary>
        static CharmerHelp()
        {
            //List<string> lisPath = new List<string>();
            //string path = AppDomain.CurrentDomain.BaseDirectory + @"HKCharmerDLL";
            //lisPath.Add(path);
            //DllImportHelp.AddEnvironmentPaths(lisPath);
        }

        /// <summary>
        /// 初始化(初始化在调用任何接口之前 多个相机只需要初始化一次即可)
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        [Obsolete("现在使用参数初始化")]
        public bool InitCharmer(out string error)
        {
            error = "";
            if (m_bInitSDK)
            {
                return m_bInitSDK;
            }
            m_bInitSDK = CHCNetSDK.NET_DVR_Init();
            if (m_bInitSDK == false)
            {
                error = "NET_DVR_Init error!";
            }
            else
            {

                //保存SDK日志 To save the SDK log
                CHCNetSDK.NET_DVR_SetLogToFile(3, $"{AppDomain.CurrentDomain.BaseDirectory}logs\\SdkLog\\", true);
            }
            return m_bInitSDK;
        }

        /// <summary>
        /// 初始化(初始化在调用任何接口之前 多个相机只需要初始化一次即可)
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public static bool InitCharmerSDK(out string error)
        {
           
            error = "";
            if (m_bInitSDK)
            {
                return m_bInitSDK;
            }
            m_bInitSDK = CHCNetSDK.NET_DVR_Init();
            if (m_bInitSDK == false)
            {
                error = "NET_DVR_Init error!";
            }
            else
            {
                //保存SDK日志 To save the SDK log
                CHCNetSDK.NET_DVR_SetLogToFile(3, $"{AppDomain.CurrentDomain.BaseDirectory}logs\\SdkLog\\", true);
            }
            return m_bInitSDK;
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool UnInit()
        {
            return CHCNetSDK.NET_DVR_Cleanup();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool Login(out string error)
        {
            error = "";
            if (m_UserID != -1)
            {
                return true;
            }
            string port = Port.ToString();
            CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();

            //登录设备 Login the device
            m_UserID = CHCNetSDK.NET_DVR_Login_V30(IpAdress, Port, UserName, PassWord, ref DeviceInfo);
            if (m_UserID < 0)
            {
                uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                error = "NET_DVR_Login_V30 failed, error code= " + iLastErr; //登录失败，输出错误号
                return false;
            }
            else
            {
                //登录成功
                return true;
            }
        }

        /// <summary>
        /// 开启实时视频
        /// </summary>
        /// <param name="videoHandel"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        [Obsolete("请使用RealPlay30")]
        public bool RealPlay(IntPtr videoHandel, out string error)
        {
            error = "";
            if (m_lRealHandle != -1)
            {
                return true;
            }

            CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
            lpPreviewInfo.hPlayWnd = videoHandel;//预览窗口
            lpPreviewInfo.lChannel = CatchImageChannel;//预te览的设备通道
            lpPreviewInfo.dwStreamType = 0;//码流类型：0-主码流，1-子码流，2-码流3，3-码流4，以此类推
            lpPreviewInfo.dwLinkMode = 0;//连接方式：0- TCP方式，1- UDP方式，2- 多播方式，3- RTP方式，4-RTP/RTSP，5-RSTP/HTTP 
            lpPreviewInfo.bBlocked = true; //0- 非阻塞取流，1- 阻塞取流
            lpPreviewInfo.dwDisplayBufNum = 1; //播放库播放缓冲区最大缓冲帧数
            lpPreviewInfo.byProtoType = 0;
            lpPreviewInfo.byPreviewMode = 0;

            if (RealData == null)
            {
                RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数
            }

            IntPtr pUser = new IntPtr();//用户数据

            //打开预览 Start live view 
            m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V40(m_UserID, ref lpPreviewInfo, null, pUser);
            if (m_lRealHandle == -1)
            {
                uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                error = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败，输出错误号
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 开启实时视频(兼容性最强,且跨平台)
        /// </summary>
        /// <param name="videoHandel"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool RealPlay30(IntPtr videoHandel, out string error)
        {
            error = "";
            if (m_lRealHandle != -1)
            {
                return true;
            }

            CHCNetSDK.NET_DVR_CLIENTINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_CLIENTINFO();
            lpPreviewInfo.hPlayWnd = videoHandel;//预览窗口
            lpPreviewInfo.lChannel = CatchImageChannel;//预te览的设备通道
            lpPreviewInfo.lLinkMode = 0x80000000;

            if (RealData == null)
            {
                RealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);//预览实时流回调函数
            }

            IntPtr pUser = new IntPtr();//用户数据

            //打开预览 Start live view 
            m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V30(m_UserID, ref lpPreviewInfo, null, pUser,0);
            if (m_lRealHandle == -1)
            {
                uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                error = "NET_DVR_RealPlay_V40 failed, error code= " + iLastErr; //预览失败，输出错误号
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 开始保存实时视频
        /// </summary>
        /// <param name="path"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool SaveRealDate(string path, out string error)
        {
            error = "";
           bool result= CHCNetSDK.NET_DVR_SaveRealData(m_lRealHandle, path);
           if (!result)
           {
               uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
               error = "开始录像失败 " + iLastErr; //预览失败，输出错误号
               return false;
            }
           return true;
        }

        public bool StopRealDate(out string error)
        {
            error = "";
            bool result = CHCNetSDK.NET_DVR_StopSaveRealData(m_lRealHandle);
            if (!result)
            {
                uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                error = "停止录像失败 " + iLastErr; //预览失败，输出错误号
                return false;
            }
            return result;
        }


        #region 回调
        /// <summary>
        /// 实时视频的回调函数
        /// </summary>
        /// <param name="lRealHandle"></param>
        /// <param name="dwDataType"></param>
        /// <param name="pBuffer"></param>
        /// <param name="dwBufSize"></param>
        /// <param name="pUser"></param>
        public void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser)
        {
          
            
        }

        public void InitResultByteCallBaack(Action<Byte[], string> ResultByteCallBaack)
        {
            this.ResultByteCallBaack = ResultByteCallBaack;
        }

        public void StartGetBaytes()
        {
            if (ResultByteCallBaack == null)
            {
                return;
            }

            if (!m_HaveStartCatchThread)
            {
                lock (m_LockHaveStartCatchThread)
                {
                    if (!m_HaveStartCatchThread)
                    {
                        Thread thread = new Thread(StartGetBytes);
                        thread.IsBackground = true;
                        thread.Start();
                    }
                    m_HaveStartCatchThread = true;
                }
            }
            else
            {
                m_IsContinueCatch = true;
            }
           
        }

        public void StopGetBaytes()
        {
            m_IsContinueCatch = false;
        }



        private void StartGetBytes()
        {
            while (true)
            {
                try
                {
                    if (!m_IsContinueCatch)
                    {
                        Thread.Sleep(10);
                        continue;
                    }
                    DateTime dtBeginTime=DateTime.Now;
                    CatchImageTrigger();
                    TimeSpan ts = DateTime.Now - dtBeginTime;
                    if (ts.TotalMilliseconds<333)
                    {
                        Thread.Sleep(Convert.ToInt32(333- ts.TotalMilliseconds));
                    }
                }
                catch (Exception exception)
                {
                   // LogHelp.AddLog($"线程抓拍相机图片异常", exception);
                }
            }
        }

        private void StartCatchImage()
        {

        }

        /// <summary>
        /// 抓拍图片
        /// </summary>
        public void CatchImageTrigger()
        {
            string error;
            Byte[] imageBytes = CatchBytes(out error);
            if (imageBytes == null)
            {
                return;
            }

            if (ResultByteCallBaack != null)
            {
                ResultByteCallBaack(imageBytes, this.IpAdress);
            }
        }

        public static volatile int m_Index = 4;

        public static volatile int count = 0;

        /// <summary>
        /// 获取图片
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public Byte[] CatchBytes(out string error)
        {
            error = "";
            //lock (m_LockObject)
            //{
            //    Byte[] testbytes = File.ReadAllBytes($@"F:\轮胎吊相关\2020年11月12日\Container\192.168.10.22\20201112\20201112162754_5d11044e-6a3a-47bd-8242-8deaf3012011.jpg");
            //    Thread.Sleep(500);
            //    return testbytes;
            //}



            uint iBuffSize = 1000000; //缓冲区大小需要不小于一张图片数据的大小 The buffer size should not be less than the picture size
            byte[] byJpegPicBuffer = new byte[iBuffSize];
            uint dwSizeReturned = 0;
            CHCNetSDK.NET_DVR_JPEGPARA netDvrJpegpara = new CHCNetSDK.NET_DVR_JPEGPARA();
            netDvrJpegpara.wPicQuality = 1;
            netDvrJpegpara.wPicSize = 0;
            lock (m_LockObject)
            {
                //加锁 一次只能获取一张
                bool bolIsSuccess = CHCNetSDK.NET_DVR_CaptureJPEGPicture_NEW(m_UserID, CatchImageChannel, ref netDvrJpegpara, byJpegPicBuffer,
               iBuffSize, ref dwSizeReturned);
                if (!bolIsSuccess)
                {
                    uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    error = $"相机  {IpAdress} 抓图失败 错误编码{iLastErr}";
                    return null;
                }
            }

            Byte[] returnBytes = new byte[dwSizeReturned];
            Buffer.BlockCopy(byJpegPicBuffer, 0, returnBytes, 0, returnBytes.Length);
            return returnBytes;
        }

        private static bool m_HaveSetModel = false;

        private static object m_LockHaveSetModel = new object();

        public Byte[] CatchRealPlayBytes(out string error)
        {
            error = "";
            //lock (m_LockObject)
            //{
            //    Byte[] testbytes = File.ReadAllBytes($@"F:\轮胎吊相关\2020年11月12日\Container\192.168.10.22\20201112\20201112162754_5d11044e-6a3a-47bd-8242-8deaf3012011.jpg");
            //    Thread.Sleep(500);
            //    return testbytes;
            //}
            if (m_HaveSetModel == false)
            {
                lock (m_LockHaveSetModel)
                {
                    if (!m_HaveSetModel)
                    {
                        //设置图片格式 0 bmp 1 jpg
                        CHCNetSDK.NET_DVR_SetCapturePictureMode(1);
                        m_HaveSetModel = true;
                    }
                }
            }
            
            
            uint iBuffSize = 1000_0000; //缓冲区大小需要不小于一张图片数据的大小 The buffer size should not be less than the picture size
            byte[] byJpegPicBuffer = new byte[iBuffSize];
            uint dwSizeReturned = 0;
            lock (m_LockObject)
            {
                //加锁 一次只能获取一张
                bool bolIsSuccess = CHCNetSDK.NET_DVR_CapturePictureBlock_New(this.m_lRealHandle, byJpegPicBuffer,
                    iBuffSize, ref dwSizeReturned);
                if (!bolIsSuccess)
                {
                    uint iLastErr = CHCNetSDK.NET_DVR_GetLastError();
                    error = $"相机  {IpAdress} 抓图失败 错误编码{iLastErr}";
                    return null;
                }
            }

            Byte[] returnBytes = new byte[dwSizeReturned];
            Buffer.BlockCopy(byJpegPicBuffer, 0, returnBytes, 0, returnBytes.Length);
            return returnBytes;
        }

        /// <summary>
        /// 获取抓拍图片的句柄
        /// </summary>
        /// <param name="error"></param>
        /// <returns></returns>
        public IntPtr GetCatchIntPtr(out string error)
        {
            try
            {
                Byte[] bytes = CatchBytes(out error);
                if (!string.IsNullOrEmpty(error))
                {
                    return IntPtr.Zero;
                }

                IntPtr intPtr = Marshal.AllocHGlobal(bytes.Length);

                //在处理完算法后释放
                Marshal.Copy(bytes, 0, intPtr, bytes.Length);
                return intPtr;

            }
            catch (Exception e)
            {
                error = e.Message;
                return IntPtr.Zero;
            }
           
        }

        /// <summary>
        /// 日志实体写日志文件
        /// </summary>
        /// <param name="logEncity"></param>
        /// <returns></returns>
        private static bool TryWrite(string message)
        {
            try
            {
                string m_LogFolderPath = "图片";
                if (!Directory.Exists(m_LogFolderPath))
                {
                    Directory.CreateDirectory(m_LogFolderPath);
                }
                string logFileName = "1.txt";
                string logFilePath = $"{m_LogFolderPath}\\{logFileName}";


                using (StreamWriter sw = File.AppendText(logFilePath))
                {
                    sw.Write(message);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
            return false;
        }

        private string Base(string str)
        {
            byte[] b = Encoding.Default.GetBytes(str);
            //转成 Base64 形式的 System.String  
            str = Convert.ToBase64String(b);
            return str;

        }
        #endregion


    }
}
